package com.chenfan.common.extension.mybatisplus.enhanced;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.apache.ibatis.annotations.Param;

import java.util.Collection;
import java.util.List;

/**
 * BaseMapper增强
 *
 * @author wulg
 * @date 2021-08-26
 **/
public interface EnhancedBaseMapper<T> extends BaseMapper<T> {

    /**
     * 批量新增
     *
     * @param list {@link Collection<T> }
     * @return int
     */
    int insertBatch(Collection<T> list);

    /**
     * 批量插入或更新
     *
     * @param list {@link Collection<T> }
     * @return int
     */
    int saveBatch(Collection<T> list);

    /**
     * 根据 entity 条件，查询一条记录，并锁定
     *
     * @param queryWrapper 实体对象封装操作类（可以为 null）
     */
    T selectOneForUpdate(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);


    /**
     * 根据 entity 条件，查询全部记录，并锁定
     *
     * @param queryWrapper 实体对象封装操作类（可以为 null）
     */
    List<T> selectListForUpdate(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

    /**
     * 存在
     *
     * @param queryWrapper {@link Wrapper<T>}
     * @return boolean
     */
    default boolean exist(Wrapper<T> queryWrapper) {
        if (queryWrapper != null && queryWrapper instanceof LambdaQueryWrapper) {
            ((LambdaQueryWrapper<T>) queryWrapper).last(" limit 1");
        }
        return this.selectCount(queryWrapper) > 0;
    }

    /**
     * 不存在
     *
     * @param queryWrapper {@link Wrapper<T>}
     * @return boolean
     */
    default boolean notExist(Wrapper<T> queryWrapper) {
        if (queryWrapper != null && queryWrapper instanceof LambdaQueryWrapper) {
            ((LambdaQueryWrapper<T>) queryWrapper).last(" limit 1");
        }
        return this.selectCount(queryWrapper) <= 0;
    }

    /**
     * 新增或修改
     *
     * @param entity {@link T}
     * @return boolean
     */
    default int save(T entity) {
        if (null == entity) {
            return 0;
        } else {
            TableInfo tableInfo = TableInfoHelper.getTableInfo(entity.getClass());
            Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!", new Object[0]);
            String keyProperty = tableInfo.getKeyProperty();
            Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!", new Object[0]);
            Object idVal = ReflectionKit.getFieldValue(entity, tableInfo.getKeyProperty());
            return !StringUtils.checkValNull(idVal) ? this.updateById(entity) : this.insert(entity);
        }
    }

    /**
     * 无策略更新-可忽略全局FieldStrategy（注：字段置NULL无须自定义SQL）
     * @param updateWrapper
     * @return
     */
    default boolean updateByNoStrategy(LambdaUpdateWrapper<T> updateWrapper) {
        return this.update(null, updateWrapper) > 0;
    }
}
